﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using LaunchMeNot.Core;
using Lime49;
using Lime49.UI;
using Microsoft.Win32;

namespace LaunchMeNot
{
    /// <summary>
    /// Window for adding/editing startup entries.
    /// </summary>
    public partial class WinAddEntry : Window
    {
        public static readonly DependencyProperty SelectedEntryProperty = DependencyProperty.Register("SelectedEntry", typeof(IStartupEntry), typeof(WinAddEntry), new PropertyMetadata(new LaunchMeNotEntry(), new PropertyChangedCallback(SelectedEntry_Changed)));
        private static void SelectedEntry_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WinAddEntry dlg = d as WinAddEntry;
            if (dlg == null || dlg.SelectedEntry == null)
                return;
            dlg.UpdateFields();
        }

        /// <summary>
        /// Gets or sets the currently selected entry.
        /// </summary>
        /// <value>The selected entry.</value>
        public IStartupEntry SelectedEntry
        {
            get { return base.GetValue(SelectedEntryProperty) as IStartupEntry; }
            set { base.SetValue(SelectedEntryProperty, value); }
        }

        public event ReqestSaveDelegate RequestSave;

        /// <summary>
        /// Initializes a new <see cref="WinAddEntry"/> to add a specific type of entry.
        /// </summary>
        /// <param name="entryType">Type of the entry.</param>
        public WinAddEntry(Type entryType)
        {
            InitializeComponent();
            //string[] typeN
            Dictionary<StartupEntryType, string> availableTypes = new Dictionary<StartupEntryType, string>()
            {
                {StartupEntryType.LaunchMeNot,"LaunchMeNot"},
                {StartupEntryType.LocalMachineRun, I18nUtils.GetString("Strings", "RegistryLocalMachineRun") },
                {StartupEntryType.CurrentUserRun,I18nUtils.GetString("Strings", "RegistryCurrentUserRun")},
                {StartupEntryType.AllUsersStartup,I18nUtils.GetString("Strings", "AllUsersStartupFolder")},
                {StartupEntryType.CurrentUserStartup, I18nUtils.GetString("Strings", "CurrentUserStartupFolder")}
            };
            cboEntryType.ItemsSource = availableTypes;// EnumBinder.EnumHelper.ToList<string>(typeof(StartupEntryType));
            if (entryType == typeof(LaunchMeNotEntry)) {
                SelectedEntry = new LaunchMeNotEntry();
            } else {
                SelectedEntry = new StartupEntryBase();
            }
        }

        /// <summary>
        /// Initializes a new <see cref="WinAddEntry"/>.
        /// </summary>
        public WinAddEntry()
            :this(typeof(LaunchMeNotEntry))
        {   
        }

        /// <summary>
        /// Initializes a new <see cref="WinAddEntry"/> to edit an entry.
        /// </summary>
        /// <param name="entry">The entry to edit.</param>
        public WinAddEntry(IStartupEntry entry)
            : this(entry.GetType())
        {
            SelectedEntry = entry;
            Title = I18nUtils.GetString("Strings", "EditEntry");
            btnOk.Content = I18nUtils.GetString("Strings", "Save");
            lblEntryType.Visibility = Visibility.Collapsed;
            cboEntryType.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// Updates the fields shown for the type of entry selected.
        /// </summary>
        private void UpdateFields()
        {
            Visibility delayVisibility = Visibility.Collapsed,
                       isEnabledVisibility = Visibility.Collapsed,
                       descriptionVisibility = Visibility.Collapsed;
            switch (SelectedEntry.EntryType) {
                case StartupEntryType.LaunchMeNot:
                    delayVisibility = Visibility.Visible;
                    isEnabledVisibility = Visibility.Visible;
                    descriptionVisibility = Visibility.Visible;
                    break;
                case StartupEntryType.AllUsersStartup:
                case StartupEntryType.CurrentUserStartup:
                    descriptionVisibility = Visibility.Visible;
                    break;
            }
            lblDelay.Visibility = delayVisibility;
            txtDelay.Visibility = delayVisibility;
            chkIsEnabled.Visibility = isEnabledVisibility;
            lblDescription.Visibility = descriptionVisibility;
            txtDescription.Visibility = descriptionVisibility;
        }

        /// <summary>
        /// Shows an OpenFileDialog to browse.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void Browse(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog dlgOpen = new OpenFileDialog
                                         {
                                             CheckPathExists = false,
                                             ValidateNames = false,
                                             Filter = string.Format("{0}|*.*|{1}|*.exe;*.cmd;*.com;*.pif;*.bat",
                                                                    I18nUtils.GetString("Strings", "AllFiles"),
                                                                    I18nUtils.GetString("Strings", "Programs")),
                                             FilterIndex = 2,
                                             Title = I18nUtils.GetString("Strings", "Browse"),
                                             Multiselect = false
                                         };
            string lastPath = Properties.Settings.Default.LastNewEntryPath;
            dlgOpen.FileName = lastPath;
            if (dlgOpen.ShowDialog() == true) {
                SelectedEntry.Path = dlgOpen.FileName;
                if (string.IsNullOrEmpty(SelectedEntry.Name)) {
                    try {
                        SelectedEntry.Name = System.IO.Path.GetFileName(SelectedEntry.Path);
                    } catch { /* Invalid path */ }
                }
            }
        }

        /// <summary>
        /// Validates the data entered.
        /// </summary>
        /// <returns><c>true</c> if this entry is valid, otherwise <c>false</c>.</returns>
        private bool ValidateEntry()
        {
            bool valid = true;
            if (string.IsNullOrEmpty(SelectedEntry.Name)) {
                DialogBox.ShowAlert(this, I18nUtils.GetString("Errors", "NameIsRequired"), I18nUtils.GetString("Errors", "Error"));
                txtName.Focus();
                valid = false;
            } else if (string.IsNullOrEmpty(SelectedEntry.Path)) {
                DialogBox.ShowAlert(this, I18nUtils.GetString("Errors", "PathToLaunchIsRequired"), I18nUtils.GetString("Errors", "Error"));
                txtPath.Focus();
                valid = false;
            } else if ((!System.IO.File.Exists(SelectedEntry.Path)) && DialogBox.Show(this, I18nUtils.GetString("Strings", "PathInvalidContinuePrompt"), I18nUtils.GetString("Errors", "FileDoesNotExist"), DialogBoxType.YesNo, DialogBoxIcon.Warning, DialogBoxButton.No) != DialogBoxButton.Yes) {
                txtPath.Focus();
                valid = false;
            }
            return valid;
        }

        /// <summary>
        /// Validates, then saves the entry.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void SaveEntry(object sender, ExecutedRoutedEventArgs e)
        {
            if (ValidateEntry()) {
                if(RequestSave == null || RequestSave(SelectedEntry))
                    DialogResult = true;
            }
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Updates the entry when the selected type changes.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void cboEntryType_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            if (e.RemovedItems.Count == 0 || cboEntryType.SelectedValue == null)
                return;
            StartupEntryType selectedType = (StartupEntryType)Enum.Parse(typeof(StartupEntryType), Convert.ToString(cboEntryType.SelectedValue), true);
            switch (selectedType) {
                case StartupEntryType.AllUsersStartup:
                    SelectedEntry = new ShellShortcut(SelectedEntry) { EntryType = StartupEntryType.AllUsersStartup };
                    break;
                case StartupEntryType.CurrentUserStartup:
                    SelectedEntry = new ShellShortcut(SelectedEntry) { EntryType = StartupEntryType.CurrentUserStartup };
                    break;
                case StartupEntryType.CurrentUserRun:
                    SelectedEntry = new RegistryShortcut(SelectedEntry) { EntryType = StartupEntryType.CurrentUserRun };
                    break;
                case StartupEntryType.LocalMachineRun:
                    SelectedEntry = new RegistryShortcut(SelectedEntry) { EntryType = StartupEntryType.LocalMachineRun };
                    break;
                case StartupEntryType.LaunchMeNot:
                default:
                    SelectedEntry = new LaunchMeNotEntry(SelectedEntry) { EntryType = StartupEntryType.LaunchMeNot };
                    break;
            }
            //SelectedEntry = new 
        }
    }
}